package com.boarsoft.boar.batch.action;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.boarsoft.boar.batch.biz.BatchInstBiz;
import com.boarsoft.boar.batch.entity.BatchInst;
import com.boarsoft.boar.batch.quartz.QuartzSchedulerMonitor;
import com.boarsoft.boar.batch.service.BatchInstService;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.common.Authorized;
import com.boarsoft.common.Util;
import com.boarsoft.common.action.PageAction;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.common.util.JsonUtil;

@SuppressWarnings("serial")
@Component
@Scope("prototype")
@ParentPackage("default-package")
@Namespace(value = "/inst")
public class BatchInstAction extends PageAction {

	@Autowired
	private BatchInstBiz instBiz;
	
	@Autowired(required = false)
	@Qualifier("schedulerMonitor")
	private QuartzSchedulerMonitor monitor;

	@Autowired(required = false)
	@Qualifier("monitorBroadcast")
	private BatchInstService instService;

	private String addr;

	private String catalog;
	
	@Action("list")
	@Authorized(code = "batch.inst.list")
	public void list() {
		try {
			int timeout = monitor.getTimeout();
			List<Object[]> oLt = instBiz.list(monitor.getCatalog());
			List<HashMap<String, Object>> rLt = new ArrayList<HashMap<String, Object>>();
			Timestamp maxLockTime = null;// lockTime最大值
			HashMap<String, Object> maxMap = null;// lockTime最大值对应数据
			for (Object[] oa : oLt) {
				BatchInst bi = (BatchInst) oa[0];
				Timestamp currTimestamp = (Timestamp) oa[1];
				HashMap<String, Object> map = new HashMap<String, Object>(4);
				map.put("addr", bi.getAddr());
				map.put("catalog", bi.getCatalog());
				map.put("lockTime", bi.getLockTime().toString());
				map.put("lastTime", bi.getLastTime().toString());
				String status = null;
				if (currTimestamp.getTime() - bi.getLockTime().getTime() <= timeout * 1000L) {
					if (maxLockTime == null || maxLockTime.compareTo(bi.getLastTime()) < 0) {
						// 判断并记录lockTime最大值，及其对应的数据
						maxLockTime = bi.getLockTime(); //
						maxMap = map;
					}
					// status = "2";// running
					status = "1";// standby
				} else if (currTimestamp.getTime() - bi.getLastTime().getTime() <= timeout * 4 * 1000L) {
					status = "1";// standby
				} else {
					status = "0";// stopped
				}
				map.put("status", status);
				rLt.add(map);
			}
			if (maxMap != null)
				maxMap.put("status", "2");// 将lockTime最大的数据的状态设置为主调度
			PagedResult<HashMap<String, Object>> pr = new PagedResult<HashMap<String, Object>>(//
					rLt.size(), rLt, pageNo, pageSize);
			writeReply(true, JsonUtil.from(pr));
		} catch (Exception e) {
			log.error("Error on list batch inst", e);
			writeReply(Constants.ERROR_UNKNOWN);
		}
	}

	@SuppressWarnings("unchecked")
	@Action("master")
	@Authorized(code = "batch.inst.master")
	public void master() {
		if (Util.strIsEmpty(addr)) {
			writeReply(Constants.ERROR_INVALID, "addr");
			return;
		}
		if (Util.strIsEmpty(catalog)) {
			writeReply(Constants.ERROR_INVALID, "catalog");
			return;
		}
		try {
			// 注册新的主调度
			BatchInst nm = new BatchInst();
			nm.setAddr(addr);
			nm.setCatalog(catalog);
			instBiz.lock(nm);

			// broadcast 停止所有调度
			monitor.stopAll();// 自己
			Map<String, Object> stopResultMap = (Map<String, Object>) instService.stopAll();
			if (stopResultMap.isEmpty()) {
				writeReply("\"{0}\"", "广播：停止调度，失败");
				return;
			}
			for (Entry<String, Object> entry : stopResultMap.entrySet()) {
				Object value = entry.getValue();
				if (value instanceof Throwable) {
					log.error("[{}]".concat(((Throwable) value).getMessage()), entry.getKey(), (Throwable) value);
					writeReply("\"{0}\"", "广播：停止调度，收到失败应答");
					return;
				}
			}
			// broadcast 设置主调度：即启动目标调度
			monitor.start(nm);
			Map<String, Object> startResultMap = (Map<String, Object>) instService.start(nm);
			if (startResultMap.isEmpty()) {
				writeReply("\"{0}\"", "广播：设置主调度，失败");
				return;
			}
			for (Entry<String, Object> entry : startResultMap.entrySet()) {
				Object value = entry.getValue();
				if (value instanceof Throwable) {
					log.error("[{}]", entry.getKey(), (Throwable) value);
					writeReply("\"{0}\"", "广播：设置主调度，收到失败应答");
					return;
				}
			}
			writeReply();
		} catch (Exception e) {
			log.error("Error on set master batch inst", e);
			writeReply("Msg.info.fail", "设置主调度");
		}
	}

	@Action("delete")
	@Authorized(code = "batch.inst.delete")
	public void delete() {
		if (Util.strIsEmpty(addr)) {
			writeReply(Constants.ERROR_INVALID, "addr");
			return;
		}
		try {
			instBiz.delete(addr);
			writeReply();
		} catch (Exception e) {
			log.error("Error on delete batch inst", e);
			writeReply(Constants.ERROR_UNKNOWN);
		}
	}

	public String getAddr() {
		return addr;
	}

	public void setAddr(String addr) {
		this.addr = addr;
	}

	public String getCatalog() {
		return catalog;
	}

	public void setCatalog(String catalog) {
		this.catalog = catalog;
	}

}
